package com.aiti.lulian.service.impl;

import cn.hutool.core.util.StrUtil;
import com.aiti.base.core.base.service.iml.BaseSerivceImpl;
import com.aiti.base.core.page.PageInfo;
import com.aiti.base.core.page.PageResult;
import com.aiti.base.core.utils.message.Message;
import com.aiti.lulian.dto.CardPromotionDto;
import com.aiti.lulian.entity.CardPromotionWithdrawRecord;
import com.aiti.lulian.entity.crad.promotion.CardPromotion;
import com.aiti.lulian.entity.crad.promotion.CardPromotionSub;
import com.aiti.lulian.mapper.promotion.CardPromotionMapper;
import com.aiti.lulian.service.ICardPromotionService;
import com.aiti.lulian.service.ICardPromotionSubService;
import com.aiti.lulian.service.ICardPromotionWithdrawRecordService;
import com.aiti.lulian.utils.PromotionCodeUtil;
import com.aiti.lulian.vo.CardPromotionVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CardPromotionServiceImpl extends BaseSerivceImpl<CardPromotionMapper, CardPromotion> implements ICardPromotionService {

    private final CardPromotionMapper baseMapper;

    private final ICardPromotionSubService cardPromotionSubService;

    @Autowired
    private ICardPromotionWithdrawRecordService withdrawRecordService;

    public CardPromotionServiceImpl(CardPromotionMapper baseMapper, ICardPromotionSubService cardPromotionSubService) {
        this.baseMapper = baseMapper;
        this.cardPromotionSubService = cardPromotionSubService;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Message addPromoter(CardPromotionDto cardPromotionDto) {
        CardPromotion cardPromotion = new CardPromotion();
        BeanUtils.copyProperties(cardPromotionDto, cardPromotion);
        cardPromotion.setPromotionCode(generatePromotionCode(cardPromotion.getAccount()));
        //存储推广人数据
        boolean save = this.save(cardPromotion);

        List<CardPromotionSub> cardPromotionSubList = cardPromotionDto.getCardPromotionSubs();
        boolean saveBatch = true;
        if (cardPromotionSubList != null && cardPromotionSubList.size() > 0) {
            List<CardPromotionSub> cardPromotionSubs = cardPromotionSubList
                    .stream()
                    .peek(i -> {
                        i.setPkId(cardPromotion.getBaseId());
                        i.setPromotionCode(generatePromotionCode(i.getAccount()));
                        i.setBaseCreateBy(cardPromotionDto.getBaseCreateBy());
                    })
                    .collect(Collectors.toList());
            //存储关联账号的数据
            saveBatch = cardPromotionSubService.saveBatch(cardPromotionSubs);
        }

        if (save && saveBatch) {
            return Message.success("新增成功");
        } else {
            return Message.fail("新增失败");
        }
    }

    @Override
    public CardPromotionVo getPromoterByBaseId(String baseId) {
        CardPromotionVo cardPromotionVo = baseMapper.selectCardPromotionByBaseId(baseId);

        LambdaQueryWrapper<CardPromotionSub> cardPromotionSubQueryWrapper = new LambdaQueryWrapper<>();
        cardPromotionSubQueryWrapper.eq(CardPromotionSub::getPkId, baseId)
                .isNull(CardPromotionSub::getDeleteTime);
        cardPromotionVo.setCardPromotionSubs(cardPromotionSubService.list(cardPromotionSubQueryWrapper));

        return cardPromotionVo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Message updatePromoter(CardPromotionDto cardPromotionDto) {
        LambdaUpdateWrapper<CardPromotion> cardPromotionUpdateWrapper = new LambdaUpdateWrapper<>();
        cardPromotionUpdateWrapper
                .set(CardPromotion::getReceivingAccountType, cardPromotionDto.getReceivingAccountType())
                .set(CardPromotion::getOpeningBank, cardPromotionDto.getOpeningBank())
                .set(CardPromotion::getReceivingAccountRealName, cardPromotionDto.getReceivingAccountRealName())
                .set(CardPromotion::getReceivingDetailedAccount, cardPromotionDto.getReceivingDetailedAccount())
                .set(CardPromotion::getBaseUpdateBy, cardPromotionDto.getBaseCreateBy())
                .eq(CardPromotion::getBaseId, cardPromotionDto.getBaseId());
        if (StrUtil.equals(cardPromotionDto.getReceivingAccountType(), "1")) {
            cardPromotionUpdateWrapper.set(CardPromotion::getOpeningBank, null);
        }
        boolean update = this.update(cardPromotionUpdateWrapper);

        LambdaQueryWrapper<CardPromotionSub> cardPromotionSubQueryWrapper = new LambdaQueryWrapper<>();
        cardPromotionSubQueryWrapper.eq(CardPromotionSub::getPkId, cardPromotionDto.getBaseId())
                .isNull(CardPromotionSub::getDeleteTime);
        //查询出原关联账号集
        List<CardPromotionSub> cardPromotionSubList = cardPromotionSubService.list(cardPromotionSubQueryWrapper);
        //收集得到 原account集
        List<String> originalAccounts = cardPromotionSubList.stream().map(i -> i.getAccount()).collect(Collectors.toList());

        //获取到现关联账号集
        List<CardPromotionSub> cardPromotionSubs = cardPromotionDto.getCardPromotionSubs();
        //收集得到 现account集
        List<String> nowAccounts = cardPromotionSubs.stream().map(i -> i.getAccount()).collect(Collectors.toList());
        //两集合做差得到被删除的account
        originalAccounts.removeAll(nowAccounts);
        if (originalAccounts.size() > 0) {
            //进行删除处理
            cardPromotionSubService.removePromotionSubByAccounts(originalAccounts);
        }

        //收集得到该推广人新添的关联账号
        List<CardPromotionSub> newCardPromotionSubs = cardPromotionSubs.stream().filter(i -> StrUtil.isEmpty(i.getBaseId())).collect(Collectors.toList());
        if (newCardPromotionSubs.size() > 0) {
            //构建新关联账号的数据对象
            List<CardPromotionSub> newCardPromotionSubList = newCardPromotionSubs
                    .stream()
                    .peek(i -> {
                        i.setPkId(cardPromotionDto.getBaseId());
                        i.setPromotionCode(generatePromotionCode(i.getAccount()));
                        i.setBaseCreateBy(cardPromotionDto.getBaseCreateBy());
                    })
                    .collect(Collectors.toList());
            //存储新关联账号
            boolean saveBatch = cardPromotionSubService.saveBatch(newCardPromotionSubList);

            if (update && saveBatch) {
                return Message.success("更新成功");
            } else {
                return Message.fail("更新失败");
            }
        }

        return Message.success("更新成功");
    }

    @Override
    public Message queryPromoterByEnterpriseId(String enterpriseId) {
        return Message.success(baseMapper.selectPromoterByEnterpriseId(enterpriseId));
    }

    @Override
    public Message queryIsDeletable(String baseId) {
        if (StrUtil.isNotBlank(baseId)) {
            CardPromotionSub cardPromotionSub = cardPromotionSubService.getById(baseId);
            if (cardPromotionSub != null) {
                BigDecimal cumulativeGain = cardPromotionSub.getCumulativeGain();
                if (cumulativeGain != null && cumulativeGain.compareTo(BigDecimal.ZERO) > 0) {
                    //查询到该关联账号已产生累计收益，不可删除
                    return Message.success(false);
                } else {
                    return Message.success(true);
                }
            }
        }
        return Message.success(true);
    }

    @Override
    public Message queryPromoterByEnterpriseIdExcludeSelection(String enterpriseId, String userId) {
        //默认为企业侧业务
        String promoterType = "1";
        if (StrUtil.isBlank(enterpriseId)) {
            //当该参数若为空时，则表示政府侧业务
            promoterType = "2";
        }
        return Message.success(baseMapper.selectPromoterByEnterpriseIdExcludeSelection(enterpriseId, userId, promoterType));
    }

    @Override
    public Message promotionList(Page page, CardPromotionDto dto) {
        List<CardPromotionVo> list = baseMapper.promotionList(page, dto);
        PageResult rspData = new PageResult(list, new PageInfo(dto.getPageNum(), dto.getPageSize()), page.getTotal());
        return Message.success(rspData);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Message deletePromotion(String baseId) {
        CardPromotion promotion = this.getById(baseId);
        if(promotion != null){
            BigDecimal cumulativeGain = promotion.getCumulativeGain();
            if(cumulativeGain != null && cumulativeGain.compareTo(BigDecimal.ZERO) > 0){
                return Message.fail("该推广计划已累计收益，无法删除");
            }else{
                LambdaUpdateWrapper<CardPromotion> wrapper = new LambdaUpdateWrapper<>();
                wrapper.set(CardPromotion::getDeleteTime, new Date()).eq(CardPromotion::getBaseId,baseId);
                this.update(wrapper);
                LambdaUpdateWrapper<CardPromotionSub> subWrapper = new LambdaUpdateWrapper<>();
                subWrapper.set(CardPromotionSub::getDeleteTime, new Date()).eq(CardPromotionSub::getPkId,baseId);
                cardPromotionSubService.update(subWrapper);
                return Message.success();
            }
        }else{
            return Message.success();
        }

    }

    @Override
    public Message setRatio(CardPromotionDto dto) {
        String baseId = dto.getBaseId();
        Integer ratio = dto.getRatio();
        if(!StringUtils.isEmpty(baseId)){
            if(ratio != null && ratio >= 0 && ratio <= 100){
                LambdaUpdateWrapper<CardPromotion> wrapper = new LambdaUpdateWrapper<>();
                wrapper.set(CardPromotion::getRatio, ratio).eq(CardPromotion::getBaseId,baseId);
                this.update(wrapper);
            }else{
                return Message.fail("比例应该在0-100区间");
            }

        }
        return Message.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Message withdraw(CardPromotionDto dto) {
        String baseId = dto.getBaseId();
        CardPromotion existPromotion = this.getById(baseId);
        if(!StringUtils.isEmpty(baseId) && existPromotion != null){
            BigDecimal cumulativeGain = dto.getCumulativeGain();
            BigDecimal oldcumulativeGain = existPromotion.getCumulativeGain();
            BigDecimal cumulativeGainHistory = existPromotion.getCumulativeGainHistory();
            if(oldcumulativeGain.compareTo(cumulativeGain) < 0){
                return Message.fail("提现金额不能大于累计收益(账户余额)");
            }else{
                if(cumulativeGain.compareTo(BigDecimal.ZERO) > 0){
                    LambdaUpdateWrapper<CardPromotion> wrapper = new LambdaUpdateWrapper<>();
                    wrapper.set(CardPromotion::getCumulativeGain, oldcumulativeGain.subtract(cumulativeGain))
                            .set(CardPromotion::getCumulativeGainHistory, cumulativeGainHistory.add(cumulativeGain))
                            .eq(CardPromotion::getBaseId,baseId);
                    this.update(wrapper);
                    CardPromotionWithdrawRecord record = new CardPromotionWithdrawRecord();
                    record.setUserId(existPromotion.getUserId());
                    record.setUserName(existPromotion.getRealName());
                    record.setPrice(cumulativeGain);
                    record.setPkId(baseId);
                    record.setBaseUpdateBy(dto.getBaseCreateBy());
                    withdrawRecordService.save(record);
                }

            }
        }
        return Message.success();
    }

    /**
     * 根据用户名生成唯一的推广码
     */
    private String generatePromotionCode(String username) {
        String promotionCode = PromotionCodeUtil.generatePromotionCode_62(username);

        while (! isUnique(promotionCode)) {
            username = username + System.currentTimeMillis();
            promotionCode = PromotionCodeUtil.generatePromotionCode_62(username);
        }

        return promotionCode;
    }

    /**
     * 判断推广码在存量数据中是否唯一
     */
    private Boolean isUnique(String promotionCode) {
        LambdaQueryWrapper<CardPromotion> cardPromotionQueryWrapper = new LambdaQueryWrapper<>();
        cardPromotionQueryWrapper.eq(CardPromotion::getPromotionCode, promotionCode);
        List<CardPromotion> cardPromotionList = this.list(cardPromotionQueryWrapper);
        if (cardPromotionList != null && cardPromotionList.size() > 0) {
            //说明当前已存在拥有该推广码的推广人
            return false;
        } else {
            LambdaQueryWrapper<CardPromotionSub> cardPromotionSubQueryWrapper = new LambdaQueryWrapper<>();
            cardPromotionSubQueryWrapper.eq(CardPromotionSub::getPromotionCode, promotionCode);
            List<CardPromotionSub> cardPromotionSubList = cardPromotionSubService.list(cardPromotionSubQueryWrapper);
            if (cardPromotionSubList != null && cardPromotionSubList.size() > 0) {
                //说明当前已存在拥有该推广码的关联账号
                return false;
            } else {
                return true;
            }
        }
    }
}